﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Company.Merchandising.BusinessLayer.DataEntities;
using Company.Merchandising.BusinessLayer.DataTransferObjects;
using Company.Merchandising.Security.SecurityManagement.Exceptions;

namespace Company.Merchandising.Security.SecurityManagement
{
	// trzeba pomyslec o cache'u
	// zmiana rol oraz funkcjonalnosci dla uzytkownika musi sie jednoczesnie tutaj odswiezyc
	public class SecurityManager
	{
		private const string _sessionKeyUserFaculties = "SM_UserFaculties";

		public bool IsUserAuthorizedToFaculty(string facultyName)
		{
			EnsureUserFacultiesAreInSession();
			IList<DTOFaculty> allowedFaculties = HttpContext.Current.Session[_sessionKeyUserFaculties] as IList<DTOFaculty>;

			return (from faculty in allowedFaculties where faculty.Name == facultyName select faculty).FirstOrDefault() != null;
		}

		private void EnsureUserFacultiesAreInSession()
		{
			if (HttpContext.Current.User.Identity.IsAuthenticated == false)
			{
				throw new NotLoggedUserException();
			}

			if (HttpContext.Current.Session[_sessionKeyUserFaculties] != null)
			{
				return;
			}

			using (MerchModelEntities modelEntities = new MerchModelEntities())
			{
				var credential = (from cred in modelEntities.Credential where cred.Login == HttpContext.Current.User.Identity.Name select cred).FirstOrDefault();
				if (credential == null)
				{
					//UserDoesNotExistException()
					throw new Exception();
				}

				var person = credential.Employee;
				if (person == null)
				{
					SetAllFaculties(modelEntities);
					return;
				}

				var roles = person.Roles;
				if (!roles.IsLoaded)
				{
					roles.Load();
				}

				var faculties = from role in roles select role.Faculties;
				var forbiddenFaculties = person.PermittedFaculties;
				if (!forbiddenFaculties.IsLoaded)
				{
					forbiddenFaculties.Load();
				}

				var allowedFaculties = new List<Faculty>();
				foreach (var facultyCollection in faculties)
				{
					foreach (var faculty in facultyCollection)
					{
						if (!forbiddenFaculties.Contains(faculty) && !allowedFaculties.Contains(faculty))
						{
							allowedFaculties.Add(faculty);
						}
					}
				}

				SetFacultiesToUserSession(allowedFaculties);
			}

			return;
		}

		public void RefreshUserFaculties()
		{

		}

		private void SetFacultiesToUserSession(IList<Faculty> faculties)
		{
			IList<DTOFaculty> dtoFaculties = new List<DTOFaculty>();
			foreach (var faculty in faculties)
			{
				dtoFaculties.Add(new DTOFaculty() { Id = faculty.Id, Name = faculty.Name, Description = faculty.Description });
			}

			HttpContext.Current.Session[_sessionKeyUserFaculties] = dtoFaculties;
		}

		private void SetAllFaculties(MerchModelEntities modelEntities)
		{
			SetFacultiesToUserSession((from faculty in modelEntities.Faculty select faculty).ToList());
		}
	}
}
